﻿using Kimd.Logic;
using Kimd.Machine;
using Kimd.Motion;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WorkStation.Common;

namespace WorkStation.Logic
{
    /// <summary>
    /// 上Tray模组
    /// </summary>
    public class FeedTrayLogic : FlowBase
    {
        private FeedTrayLogicStatus _status;
        //axis
        private Axis _feedY;
        private Axis _liftEmpty;
        private Axis _liftFull;
        //cylinder
        private Cylinder _fullTrayGrab;
        private Cylinder _fullTrayHold;
        private Cylinder _emptyTrayGrab;
        private Cylinder _emptyTrayHold;
        //sensor
        private Sensor _fullTrayTooMany;
        private Sensor _hasFullTray;
        private Sensor _emptyTrayTooMany;
        private Sensor _hasEmptyTray;
        private Sensor _fullTrayLiftHasTray;
        private Sensor _emptyTrayLiftHasTray;
        private Sensor _ionizerAlarm;
        private Sensor _safetyBeamA;
        private Sensor _safetyBeamB;
        //tray
        private Tray _trayStatus;
        public FeedTrayLogic(string flowName, FlowManager flowmanager) 
            : base(flowName, flowmanager)
        {
            //axis
            _feedY = MachineResource.Instance.MachineAxis["上料仓Y轴"];
            _liftEmpty = MachineResource.Instance.MachineAxis["上料仓空盘顶升"];
            _liftFull = MachineResource.Instance.MachineAxis["上料仓来料顶升"];
            //cylinder
            _fullTrayGrab = MachineResource.Instance.MachineCylinder["上料仓满盘移载定位"];
            _fullTrayHold = MachineResource.Instance.MachineCylinder["上料仓满盘区夹持气缸"];
            _emptyTrayGrab = MachineResource.Instance.MachineCylinder["上料仓空盘移载定位"];
            _emptyTrayHold = MachineResource.Instance.MachineCylinder["上料仓空盘区夹持气缸"];
            //sensor
            _fullTrayTooMany = MachineResource.Instance.MachineSensor["上料仓满盘区满盘信号"];
            _hasFullTray = MachineResource.Instance.MachineSensor["上料仓满盘区有盘信号"];
            _emptyTrayTooMany = MachineResource.Instance.MachineSensor["上料仓空盘区满盘信号"];
            _hasEmptyTray = MachineResource.Instance.MachineSensor["上料仓空盘区有盘信号"];
            _fullTrayLiftHasTray = MachineResource.Instance.MachineSensor["上料仓满盘移载有盘"];
            _emptyTrayLiftHasTray = MachineResource.Instance.MachineSensor["上料仓空盘移载有盘"];

            _ionizerAlarm = MachineResource.Instance.MachineSensor["上料仓离子风扇报警"];
            _safetyBeamA = MachineResource.Instance.MachineSensor["上料仓安全光栅A"];
            _safetyBeamB = MachineResource.Instance.MachineSensor["上料仓安全光栅B"];
            //tray
            _trayStatus = new Tray(1, 2);
            _trayStatus.Helper.NewEmptyTray();
            //signal
            RegisterDirectSignal("取料位置有Tray");
            RegisterDirectSignal("可以取前半");
            RegisterDirectSignal("可以取后半");
        }

        public override void Calibrate()
        {
            base.Calibrate();
        }

        public override void Home()
        {
            if (!CheckFlowCondition()) return;
            //clear warn and set servo on
            _liftFull.ClearAlarm();
            Thread.Sleep(200);
            _liftFull.SetServoOn();
            _liftEmpty.ClearAlarm();
            Thread.Sleep(200);
            _liftEmpty.SetServoOn();
            _feedY.ClearAlarm();
            Thread.Sleep(200);
            _feedY.SetServoOn();

            //z轴抬起后方可回零
            WaitForSignal("取料逻辑", "Z轴已抬起");
            if (!CheckFlowCondition()) return;

            //WaitSensorOff(_hasFullTray, "上料仓满盘区有盘,请取走!");
            if (!CheckFlowCondition()) return;
            //WaitSensorOff(_hasEmptyTray, "上料仓空盘区有盘,请取走!");
            if (!CheckFlowCondition()) return;

            if (!GlobalVariable.IsSystemAlreadyHome)
                AxisGoHomeSimultaneously(new List<Axis>() { _liftEmpty, _liftFull });
            else
                AxisMoveSimultaneously(new List<Axis>() { _liftEmpty, _liftFull }, new List<double>() { 0, 0 });
            if (!CheckFlowCondition()) return;
            if (!GlobalVariable.IsSystemAlreadyHome)
                SingleAxisGoHome(_feedY);
            else
                SingleAxisMove2Point(_feedY, 0);
            if (!CheckFlowCondition()) return;

            AxisMoveSimultaneously(new List<Axis>() { _liftEmpty, _liftFull }, "移盘高度");
            if (!CheckFlowCondition()) return;
            MultiCylinderOperate(new List<Cylinder>() { _emptyTrayGrab, _fullTrayGrab }, 5000, new List<bool>() { false, false });
            if (!CheckFlowCondition()) return;

            _status = FeedTrayLogicStatus.FirstTimeRun;
        }

        public override void Init(out string errInfo)
        {
            base.Init(out errInfo);
        }

        public override void InSingleRunMode()
        {
            base.InSingleRunMode();
        }

        public override void Method()
        {
            if (!CheckFlowCondition()) return;
            switch(_status)
            {
                case FeedTrayLogicStatus.FirstTimeRun:
                    //到取盘位
                    SingleAxisMove2Point(_feedY, "取盘位");
                    if (!CheckFlowCondition()) return;
                    //取一盘待测料
                    grabOneFullTray();
                    //满盘托盘有盘
                    _trayStatus.Helper.SetCellStatus(0, CellStatus.HasProduct);
                    //到下盘位
                    SingleAxisMove2Point(_feedY, "下盘位");
                    if (!CheckFlowCondition()) return;
                    SetSignal("取料位置有Tray");
                    WaitForSignal("取料逻辑", "前半取完");
                    if (!CheckFlowCondition()) return;
                    _status = FeedTrayLogicStatus.FirstHalfDone;
                    break;

                case FeedTrayLogicStatus.FirstHalfDone:
                    //到下盘位
                    SingleAxisMove2Point(_feedY, "下盘位");
                    if (!CheckFlowCondition()) return;
                    //满盘托盘有盘，把他放下来
                    Task task1 = new Task(() =>
                    {
                        SingleAxisMove2Point(_liftFull, "落盘高度");
                        if (!CheckFlowCondition()) return;
                        SingleCylinderOperate(_fullTrayGrab, 5000, false);
                        if (!CheckFlowCondition()) return;
                    });
                    task1.Start();
                    //空盘托盘有料，把他回收
                    Task task2 = null;
                    if(_trayStatus.Helper.GetCell(1).Status == CellStatus.HasProduct)
                    {
                        task2 = new Task(() =>
                        {
                            recycleOneEmptyTray();
                        });
                        task2.Start();
                    }
                    if (task2 != null)
                        Task.WaitAll(task1, task2);
                    else
                        //等待两个任务都完成
                        Task.WaitAll(task1);
                    //刷新料盘有无状态
                    _trayStatus.Helper.SetCellStatus(0, CellStatus.NoProduct);
                    _trayStatus.Helper.SetCellStatus(1, CellStatus.NoProduct);

                    //到取盘位
                    SingleAxisMove2Point(_feedY, "取盘位");
                    if (!CheckFlowCondition()) return;

                    Task task3 = new Task(() =>
                    {
                        SingleAxisMove2Point(_liftEmpty, "取缓存高度");
                        if (!CheckFlowCondition()) return;
                        SingleCylinderOperate(_emptyTrayGrab, 5000, true);
                        if (!CheckFlowCondition()) return;
                        _trayStatus.Helper.SetCellStatus(1, CellStatus.HasProduct);
                    });
                    task3.Start();

                    Task task4 = new Task(() =>
                    {
                        grabOneFullTray();
                        //满盘托盘有盘
                        _trayStatus.Helper.SetCellStatus(0, CellStatus.HasProduct);
                    });
                    task4.Start();
                    //等待两个任务都完成
                    Task.WaitAll(task3, task4);

                    SetSignal("可以取后半");
                    WaitForSignal("取料逻辑", "后半取完");

                    _status = FeedTrayLogicStatus.SecondHalfDone;

                    break;

                case FeedTrayLogicStatus.SecondHalfDone:
                    //到下盘位
                    SingleAxisMove2Point(_feedY, "下盘位");
                    if (!CheckFlowCondition()) return;
                    //空盘托盘有料，把他回收
                    if (_trayStatus.Helper.GetCell(1).Status == CellStatus.HasProduct)
                    {
                        recycleOneEmptyTray();
                        _trayStatus.Helper.SetCellStatus(1, CellStatus.NoProduct);

                    }

                    SetSignal("取料位置有Tray");
                    WaitForSignal("取料逻辑", "前半取完");

                    _status = FeedTrayLogicStatus.FirstHalfDone;

                    break;
            }
        }

        public override void OnStop()
        {
            base.OnStop();
        }

        public override bool PreStartCheck()
        {
            return base.PreStartCheck();
        }

        public override void SpotCheck()
        {
            base.SpotCheck();
        }

        #region User Method
        private void grabOneFullTray()
        {
            SingleAxisMove2Point(_liftFull, "顶盘高度");
            if (!CheckFlowCondition()) return;
            SingleCylinderOperate(_fullTrayHold, 5000, true);
            if (!CheckFlowCondition()) return;
            SingleAxisMove2Point(_liftFull, "分盘高度");
            if (!CheckFlowCondition()) return;
            SingleCylinderOperate(_fullTrayHold, 5000, false);
            if (!CheckFlowCondition()) return;
            SingleAxisMove2Point(_liftFull, "移盘高度");
            if (!CheckFlowCondition()) return;
            SingleCylinderOperate(_fullTrayGrab, 5000, true);
            if (!CheckFlowCondition()) return;
        }
        private void recycleOneEmptyTray()
        {
            SingleAxisMove2Point(_liftEmpty, "顶盘低位");
            if (!CheckFlowCondition()) return;
            SingleCylinderOperate(_emptyTrayHold, 5000, true);
            if (!CheckFlowCondition()) return;
            SingleAxisMove2Point(_liftEmpty, "顶盘高位");
            if (!CheckFlowCondition()) return;
            SingleCylinderOperate(_emptyTrayHold, 5000, false);
            if (!CheckFlowCondition()) return;
            SingleCylinderOperate(_emptyTrayGrab, 5000, false);
            if (!CheckFlowCondition()) return;
            SingleAxisMove2Point(_liftEmpty, "移盘高度");
            if (!CheckFlowCondition()) return;
        }
        #endregion
    }

    public enum FeedTrayLogicStatus
    {
        [Description("第一次运行")]
        FirstTimeRun,
        [Description("前半取完")]
        FirstHalfDone,
        [Description("后半取完")]
        SecondHalfDone,
    }
}
